-- MonthCardM
-- created by huanghr
-- 月卡模块

module("MonthCardM", package.seeall);

local monthCardCfg = {};
local cardInfo = {};

local schedulerId;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    local month_card_CSV = get_month_card_CSV();

    local id;
    local cardType;
    local level;
    for i = 1, #month_card_CSV do

        id = month_card_CSV[i].id;
        level = month_card_CSV[i].level;
        cardType = month_card_CSV[i].card_type;

        monthCardCfg[month_card_CSV[i].id] = month_card_CSV[i];

        if cardInfo[cardType] == nil then
            cardInfo[cardType] = {};
        end

        cardInfo[cardType][level] = id;
    end
end

-- 模块初始化操作
function init()
    loadCsv();

    EventMgr.removeAll("MonthCardM");
end

-- 判断是否过期了
function isOverdue(cardType)
    local data = getCardData(cardType);
    if not data then
        -- 如果从来没购买过也当做是过期了
        return true;
    end

    -- 是否过期了
    local serverTime = TimeM.getServerTime();
    local overdue = data["overdue"] or 0;
    if overdue <= serverTime then
        return true;
    end

    return false;
end

-- 获取玩家月卡数据
function getCardData(cardType)
    local monthCardData = ME.user.dbase:query("month_card_data", {});

    return monthCardData[cardType];
end

-- 能否购买
function canActiveCard(cardType)
    if MonthCardM.getCardLevel(cardType) > 0 then
        -- 当前还未失效
        return false;
    end

    -- 功能没有开不能购买
    if cardType == "pet_camp" and not isCurTypeCardOpen("pet_camp_card") then
        return "disable_function";
    end

    return true;
end

-- 检索信息
function query(id, path)
    local m = monthCardCfg[id];

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 通过类型检索信息
function queryCardInfo(cardType, level, path)
    local cardData = cardInfo[cardType];

    if type(level) ~= "number" then
        return cardData;
    end

    local id = cardData[level];

    if id ~= nil then
        return query(id, path);
    end
end

-- 获得月卡等级
function getCardLevel(cardType)
    local data = getCardData(cardType);

    if not data then
        return 0;
    end

    -- 是否过期了
    local serverTime = TimeM.getServerTime();
    local overdue = data["overdue"] or 0;
    if overdue <= serverTime then
        return 0;
    end

    return data["level"];
end

-- 激活月卡
function active(cardType)
    -- 如果玩家已经有月卡状态了
    if 0 ~= getCardLevel() then
        return false;
    end

    -- 持续时间
    local duration = queryCardInfo(cardType, 1, "duration");

    local startTime = TimeM.calcZeroTime();
    local data = {
        ["start_time"] = startTime,
        ["overdue"]    = startTime + duration,
        ["level"]      = 1,
    };

    local monthCardData = ME.user.dbase:query("month_card_data", {});
    monthCardData[cardType] = data;

    ME.user.dbase:set("month_card_data" , monthCardData);

    return true;
end

-- 能否月卡
function canUpgrade(cardType)
    local curLevel = getCardLevel(cardType);
    if curLevel == 0 then
        return false;
    end

    -- 没有下一个等级了
    local nextLevel = curLevel + 1;
    if not query(nextLevel) then
        trace("MonthCardM", "没有下一个等级。");
        return false;
    end

    -- 消耗
    local cost = queryCardInfo(cardType, curLevel, "upgrade_cost") or {};
    for attrib, value in pairs(cost) do
        if type(attrib) == "string" and
            ME.user:queryAttrib(attrib) < value then
            -- 属性不足
            trace("MonthCardM", "%s不足，需求%d，当前%d",
                attrib, value, ME.user:queryAttrib(attrib));
            return false;
        elseif type(attrib) == "number" and
            ItemM.getAmount(ME.user, attrib) < value then
            -- 物品不足
            trace("MonthCardM", "%s不足，需求%d，当前%d",
                ItemM.query(attrib, "name"), value, ItemM.getAmount(ME.user, attrib));
            return false;
        end
    end

    -- 暂没有其他要求
    return true;
end

-- 升级
function upgrade(cardType)
    -- 先判断
    if not canUpgrade(cardType) then
        return false;
    end

    -- 先消耗
    local curLevel = getCardLevel();
    local cost = queryCardInfo(cardType, curLevel, "upgrade_cost") or {};
    for attrib, value in pairs(cost) do
        if type(attrib) == "string" then
            -- 扣除属性
            ME.user:costAttrib(attrib, value);
        elseif type(attrib) == "number" then
            -- 扣除物品
            ItemM.costAmount(ME.user, attrib, value);
        else
            assert(false, "something wrong!");
        end
    end

    local data = ME.user.dbase:query("superior", {});

    -- 等级+1，持续时间++
    data["level"] = curLevel + 1;
    data["overdue"] = data["overdue"] + query(curLevel + 1, "duration");

    -- 告诉服务器升级
    Operation.cmd_upgrade_superior();

    return true;
end

-- 下次奖励时间(倒计时)
function nextBonusTime(cardType)
    -- 上次奖励时间
    local data = getCardData(cardType) or {};

    local lastBonusTime = data["bonus_time"] or 0;
    local zeroTime = TimeM.calcZeroTime();
    local nextZero = zeroTime + SECONDS_PER_DAY;

    if lastBonusTime < zeroTime then
        return 0;
    end

    -- 下一个0点
    return nextZero - TimeM.getServerTime();
end

-- 能否领取奖励
function cantakeBonus(cardType)
    local level = getCardLevel(cardType);
    if level == 0 then
        return false;
    end

    -- 上次奖励时间
    local data = getCardData(cardType) or {};
    local lastBonusTime = data["bonus_time"] or 0;

    if isSameDay(lastBonusTime, TimeM.getServerTime(), TimeM.getTimeOffsetDifference()) then
        return false;
    end

    return true;
end

-- 每日奖励
-- 直接到服务端去领取
-- 日后扩展可以根据在dbase设置flag处理
function takeDailyBonus(cardType)
    local level = getCardLevel(cardType);
    if level == 0 then
        return false;
    end

    -- 上次奖励时间
    local data = getCardData(cardType) or {};

    local lastBonusTime = data["bonus_time"] or 0;

    if isSameDay(lastBonusTime, TimeM.getServerTime(), TimeM.getTimeOffsetDifference()) then
        return false;
    end

    -- 更新下时间
    data["bonus_time"] = TimeM.getServerTime();

    Operation.cmd_take_month_card_bonus(cardType);

    return true;
end

-- 检查当前功能有没有开启
function isCardFuncActived(cardType)
    if cardType == "pet_camp" then
        return FeatureItemM.isFeatureOpen("pet_camp");
    end

    return false;
end

-- 奖励日常奖励返回
function takeDailyBonusRet(ret)
    if ret["card_type"] == "pet_camp" then
        EventMgr.fire(event.TAKE_CAMP_CARD_RET, ret);
    end
end

-- 当前类型月卡是否开启
function isCurTypeCardOpen(switchType)
    local isOpen = ServerStatusM.query(switchType) or 0;

    return isOpen == 1;
end